#include <stdio.h>
#include <rt_misc.h>
#include "uart-communication.h"
#include "crc-calculate.h"


enum Uart_status_e ST_Uart_status = UART_IDLE;

//static TimerEvent_t uartTimeOutTimer;

#pragma import(__use_no_semihosting_swi)

struct ST_Rx_Buffer_t ST_Rx_buffer;

uint8_t ST_FIFO_TxBuffer[SENSINGTREE_UART_TX_SIZE];
uint8_t ST_FIFO_RxBuffer[SENSINGTREE_UART_RX_SIZE];

static void reinitUartReceive(void);

void Open_ST_Uart(void)
{
    UartInit(&UART_SENSINGTREE, UART_1, UART_TX, UART_RX);
    UartConfig(&UART_SENSINGTREE, RX_TX, UART_ST_BAUDRATE, UART_8_BIT, UART_1_STOP_BIT, NO_PARITY, NO_FLOW_CTRL);
}

void ST_Uart_init()
{
    //open_ST_Uart();

    FifoInit(&UART_SENSINGTREE.FifoTx, ST_FIFO_TxBuffer, SENSINGTREE_UART_TX_SIZE);
    FifoInit(&UART_SENSINGTREE.FifoRx, ST_FIFO_RxBuffer, SENSINGTREE_UART_RX_SIZE);
    UART_SENSINGTREE.IrqNotify = STUart_Irq_Notify;

    ST_Rx_buffer.currentIdx = 0;
    ST_Rx_buffer.data[ST_Rx_buffer.currentIdx] = 0;

    //TimerInit(&uartTimeOutTimer, uartTimeOutTimerEvent);
    printf("sensingtree uart init\n");
}

void Transfer_ack(enum Transfer_ack_type_t type)
{
    Open_ST_Uart();
    uint8_t txTempBuffer[] = {0xfe, 0, 0, 0, 0};
    switch(type)
    {
    case TRANSFER_ACK_OK:
        txTempBuffer[1] = 0x01;
        txTempBuffer[2] = 0x01;
        break;
    case TRANSFER_ACK_WRONG:
        txTempBuffer[1] = 0x01;
        txTempBuffer[2] = 0x02;
        break;
    default:
        return;
//		break;
    }
    uint16_t uwCRCValue = LoRa_crc_calculate(txTempBuffer, ST_TX_DATA_SIZE - 2);
    txTempBuffer[3] = (uwCRCValue >> 8) & 0xFF;
    txTempBuffer[4] = uwCRCValue &  0xFF;
    //txTempBuffer[5] = 0;//for test
    FifoFlush(&UART_SENSINGTREE.FifoTx);
    UartPutBuffer(&UART_SENSINGTREE, txTempBuffer, ST_TX_DATA_SIZE);
}

void STUart_Irq_Notify(UartNotifyId_t id)
{
    if(id == UART_NOTIFY_TX)
    {
    }
    else if(id == UART_NOTIFY_RX)
    {
        if(ST_Uart_status < UART_BEGIN_RECEIVE)
        {
            return;
        }
        uint8_t data;
        if(UartGetChar(&Uart1, &data) == 0)
        {
            if(UART_HEADER_CHECKED != ST_Uart_status)
            {
                if(0xfe == data && 0 == ST_Rx_buffer.currentIdx)
                {
                    FifoFlush(&UART_SENSINGTREE.FifoRx);
                    ST_Uart_status = UART_HEADER_CHECKED;
                    //TimerSetValue(&uartTimeOutTimer, 4000);
                    //TimerStart(&uartTimeOutTimer);
                }
                else
                {
                    reinitUartReceive();
                }
            }
            if(UART_HEADER_CHECKED == ST_Uart_status)
            {
                ST_Rx_buffer.data[ST_Rx_buffer.currentIdx] = data;
                ST_Rx_buffer.currentIdx++;
            }
            if(ST_RX_DATA_SIZE == ST_Rx_buffer.currentIdx)
            {
                FifoFlush(&UART_SENSINGTREE.FifoRx);
                ST_Rx_buffer.currentIdx = 0;
                
                //close uart
                UartDeInit(&UART_SENSINGTREE);

                uint16_t uwCRCValue = 0;
                uwCRCValue = LoRa_crc_calculate(ST_Rx_buffer.data, ST_RX_DATA_SIZE - 2);
                if(((uwCRCValue >> 8) & 0xFF) == ST_Rx_buffer.data[ST_RX_DATA_SIZE - 2] &&
                        (uwCRCValue &  0xFF) == ST_Rx_buffer.data[ST_RX_DATA_SIZE - 1])
                {
                    ST_Uart_status = UART_RECEIVE_DONE;
                }
                else
                {
                    ST_Uart_status = UART_RECEIVE_WRONG;
                }

            }
        }

    }
}



/*!
 * \brief Reinit uart receive interrupt
 */
static void reinitUartReceive(void)
{
    FifoFlush(&UART_SENSINGTREE.FifoRx);
    ST_Rx_buffer.data[0] = 0;
    ST_Rx_buffer.currentIdx = 0;
    ST_Uart_status = UART_BEGIN_RECEIVE;
}


/*!
 * \brief Function executed on uart receive Timeout event
 */
void Uart_wrong_event(void)
{
    //TimerStop(&uartTimeOutTimer);
    reinitUartReceive();
    Transfer_ack(TRANSFER_ACK_WRONG);
}



